#ifndef _POWER_FLOW_CALCULATION_
#define _POWER_FLOW_CALCULATION_
#include "gsl/gsl_matrix.h"
#include "math.h"

typedef struct {
    double Type,NodeID,Vol,VolUpLmt,VolDnLmt,Angle,Pl,Ql,Pg,Qg,P,Q,QUpLmt,QDnLmt;
}Node;

typedef struct {
    double PLoss;
    gsl_matrix *voltagee,*angle;
}Power_Calculation_Node;


typedef struct{
    gsl_matrix *TransFormer_Branch,*Normal_Branch,*PQ_Node,*PV_Node,*ESS_Node,*Swing_Node;
    int Node_Num;
}RE_IEEE14;

typedef struct {
    gsl_matrix *GB,*G,*B;
}FormGB;

typedef struct {
    Node *m_Node;
    double Total_PLoad,Total_QLoad;
    int Node_Num,GenCount,nVaribles,nEquals,nNequals;
}Form_IPM;

#define PRINT_MATRIX(m) for(int ii=0;ii<m->size1;ii++){for(int jj=0;jj<m->size2;jj++){printf("%.7lf ",gsl_matrix_get(m,ii,jj));}printf("\n");}

gsl_matrix* array2gsl(double *data,int row,int col);
void gsl_matrix_mul(gsl_matrix *a,gsl_matrix *b,gsl_matrix *c);
gsl_matrix* gsl_matrix_mul(gsl_matrix *a,gsl_matrix *b);
gsl_matrix* GetInverse(gsl_matrix *A);
gsl_matrix* gsl_matrix_add2(gsl_matrix *a,gsl_matrix *b);
gsl_matrix* gsl_matrix_sub2(gsl_matrix *a,gsl_matrix *b);
gsl_matrix* gsl_matrix_scale2(gsl_matrix *a,double x);



gsl_matrix* EqualJacobiMatrix(Node m_Node[],gsl_matrix *m_G,gsl_matrix *m_B,int Node_Num,int GenCount);
gsl_matrix* EqualHeisenMatrix(Node m_Node[],gsl_matrix* m_G,gsl_matrix *m_B,gsl_matrix* m_y,int Node_Num,int GenCount,int nEquals,int nVaribles);
gsl_matrix* InequalJacobiMatrix(int GenCount,int Node_Num);
gsl_matrix* GradsMatrix(Node m_Node[],gsl_matrix* m_G,gsl_matrix *m_B,int Node_Num,int GenCount);
gsl_matrix* GradsHeisenMatrix(Node m_Node[],gsl_matrix *m_G,gsl_matrix *m_B,int Node_Num,int GenCount);
double PLoss_Calculation(Node m_Node[],int Node_Num,gsl_matrix* m_G,gsl_matrix *m_B);
RE_IEEE14 RE_IEEE14_data();
Power_Calculation_Node Power_Calculation(gsl_matrix* G,gsl_matrix *B,gsl_matrix *PQ_Node,gsl_matrix *PV_Node,gsl_matrix *ESS_Node,gsl_matrix *Swing_Node,int Node_Num,Node m_Node[]);
Form_IPM Form_IPM_data16(gsl_matrix *PQ_Node,gsl_matrix *PV_Node,gsl_matrix *ESS_Node,gsl_matrix *Swing_Node,int Node_Num);
FormGB FormGB_former(gsl_matrix* TransFormer_Branch,gsl_matrix *Normal_Branch,gsl_matrix* PQ_Node,gsl_matrix * PV_Node,int Node_Num,Node m_Node[]);
void ModifyNodeValue(Node* m_Node,gsl_matrix* m_G,gsl_matrix* m_B,int Node_Num);
gsl_matrix* v14(Node *m_Node_Initial,int Node_Num);


RE_IEEE14 LoadData();

#endif